/**
 SofferBound.h

 \file
 Declaration of class SofferBound.

 \author Thomas Burton 
 \date 3/13/12
 \copyright 2012 BNL. All rights reserved.
*/

#ifndef _SofferBound_H_
#define _SofferBound_H_

#include <set>
#include <string>

#ifndef __CINT__
#include <boost/shared_ptr.hpp>
#endif

#include <Rtypes.h>

#include "tppmc/PartonContent.h"
#include "tppmc/PartonDistribution.h"

namespace tppmc {
   
   class Parton;
   
   namespace transversity {
      
      /**
       General kT-independent Soffer bound for the transveristy distribution.
       
       The bound is based on an unpolarised distribution, f, and a helicity
       distribution, g, such that transversity, h, obeys
             |h| = (f + g) / 2
       In keeping with current data, the u quark transversity distribution is
       positive and the d quark transversity distribution is negative i.e.
       h_u =  (f_u + g_u) / 2
       h_d = -(f_d + g_d) / 2
       If at any point the magnitude of helicity distribution exceeds the
       selected unpolarised distribution, the helicity distribution is capped
       at the unpolarised distribution i.e. |g| < f is enforced.
       kT-independence is sufficient for our purposes because we use
       transversity only to compute the probability of quark spin parallel vs.
       opposite to the parent proton. This involves the ratio of transversity
       to the unpolarised distribution. Assuming the kT dependence is the
       same as the unpolarised distribution, it cancels in the ratio.
       \todo Consider allowing the sea factor to be between -1 and +1 instead
       of just on (i.e. 1) or off (i.e. 0).
       */
      class SofferBound : public PartonDistribution {
      public:
         /**
          Default constructor.
          
          The default unpolarised distribution is CT10 if LHAPDF support is
          enables, or the LO GRV98 implementation in this package if not.
          Sea quark transversity distributions are all zero.
         */
         SofferBound();
#ifndef __CINT__
         /**
          Constructor.
          
          Initialise the Soffer bound with an unpolarised distribution f
          and a helicity distribution g.
          If enableSea is true, sea quark distributions (ubar, dbar, s, sbar)
          are evaluated according to the Soffer bound for flavours supported by
          both the input distributions, or zero for flavours
          not supported by the input distributions.
          If enableSea is false, sea quark distributions are all zero.
          Gluon transversity is always zero.
         */
         typedef boost::shared_ptr<PartonDistribution> PdfPtr;

         SofferBound(PdfPtr f, PdfPtr g, bool enableSea);
#endif
         virtual ~SofferBound();

         /**
          Evaluate the Soffer bound at x of the Parton and Q2 for all flavours.
          */
         virtual void Evaluate(const Parton&, double Q2, PartonContent&) const;

         virtual int Initialise();

         /**
          Returns true if the Parton type is supported.
          To be supported, Supports() must evaluate true for both the
          unpolarised and helicity distributions used to initialise this object.
          */
         virtual bool Supports(const Parton&) const;

         /**
          Returns a string describing the distribution.
          This is a concatenation of the unpolarised and helicity distribution
          names.
         */
         virtual std::string Name() const;

         /**
          Due to its shared-pointer arguments, writing to a ROOT file
          is not supported.
         */
         virtual Int_t Write(const char* = 0, Int_t = 0, Int_t = 0);
         
         /**
          Due to its shared-pointer arguments, writing to a ROOT file
          is not supported.
          */
         virtual Int_t Write(const char* = 0, Int_t = 0, Int_t = 0) const;

      protected:
#ifndef __CINT__
         boost::shared_ptr<PartonDistribution> mUnpolarised;//!
         boost::shared_ptr<PartonDistribution> mHelicity;//!
#endif
         bool mEnableSea;

         /**
          Returns LHAPDF::Flavour of each parton type to be computed.
          Up and down are always included. Sea quarks are included if
          mEnableSea == true. Gluon is never included.
          Skip any species not supported by the unpolarised or helicity
          distributions.
         */
         std::set<int> Lhapdf() const;
         std::set<int> mPartons; ///< LHAPDF::Flavour of each parton to compute

         ClassDef(tppmc::transversity::SofferBound, 1)
      };
      
   } // namespace transversity
} // namespace tppmc

#endif
